// 版权所有2009 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package poll

import (
	"errors"
	"io"
	"sync"
	"sync/atomic"
	"time"
)

type atomicBool int32

func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }
func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }

type FD struct {
	// 锁定sysfd并序列化对读写方法的访问。
	fdmu fdMutex

	Destroy func()

	// 截止日期
	rmu       sync.Mutex
	wmu       sync.Mutex
	raio      *asyncIO
	waio      *asyncIO
	rtimer    *time.Timer
	wtimer    *time.Timer
	rtimedout atomicBool // 达到读取截止日期时设置为真
	wtimedout atomicBool // 达到写入截止日期时设置为真

	// 这是否是正常文件。
	// 在计划9中，我们不将此程序包用于普通文件，所以这总是错误的，但该字段存在，因为fd_mutex.go中的共享代码会检查它。
	isFile bool
}

// 我们需要它来关闭解锁时的文件描述符，
// 但是真正的实现必须存在于网络包中，因为
// 它使用os.file。
func (fd *FD) destroy() error {
	if fd.Destroy != nil {
		fd.Destroy()
	}
	return nil
}

// Close处理关闭FD的锁定。
// 的实际操作在net包中。
func (fd *FD) Close() error {
	if !fd.fdmu.increfAndClose() {
		return errClosing(fd.isFile)
	}
	return nil
}

// 读取实现io.Reader。
func (fd *FD) Read(fn func([]byte) (int, error), b []byte) (int, error) {
	if err := fd.readLock(); err != nil {
		return 0, err
	}
	defer fd.readUnlock()
	if len(b) == 0 {
		return 0, nil
	}
	fd.rmu.Lock()
	if fd.rtimedout.isSet() {
		fd.rmu.Unlock()
		return 0, ErrDeadlineExceeded
	}
	fd.raio = newAsyncIO(fn, b)
	fd.rmu.Unlock()
	n, err := fd.raio.Wait()
	fd.raio = nil
	if isHangup(err) {
		err = io.EOF
	}
	if isInterrupted(err) {
		err = ErrDeadlineExceeded
	}
	return n, err
}

// Write实现io.Writer。
func (fd *FD) Write(fn func([]byte) (int, error), b []byte) (int, error) {
	if err := fd.writeLock(); err != nil {
		return 0, err
	}
	defer fd.writeUnlock()
	fd.wmu.Lock()
	if fd.wtimedout.isSet() {
		fd.wmu.Unlock()
		return 0, ErrDeadlineExceeded
	}
	fd.waio = newAsyncIO(fn, b)
	fd.wmu.Unlock()
	n, err := fd.waio.Wait()
	fd.waio = nil
	if isInterrupted(err) {
		err = ErrDeadlineExceeded
	}
	return n, err
}

// 设置与fd关联的读写截止日期。
func (fd *FD) SetDeadline(t time.Time) error {
	return setDeadlineImpl(fd, t, 'r'+'w')
}

// setReadDaildate设置与fd关联的读取截止日期。
func (fd *FD) SetReadDeadline(t time.Time) error {
	return setDeadlineImpl(fd, t, 'r')
}

// setWriteDadline设置与fd关联的写入截止日期。
func (fd *FD) SetWriteDeadline(t time.Time) error {
	return setDeadlineImpl(fd, t, 'w')
}

func setDeadlineImpl(fd *FD, t time.Time, mode int) error {
	d := t.Sub(time.Now())
	if mode == 'r' || mode == 'r'+'w' {
		fd.rmu.Lock()
		defer fd.rmu.Unlock()
		fd.rtimedout.setFalse()
	}
	if mode == 'w' || mode == 'r'+'w' {
		fd.wmu.Lock()
		defer fd.wmu.Unlock()
		fd.wtimedout.setFalse()
	}
	if t.IsZero() || d < 0 {
		// 停止计时器
		if mode == 'r' || mode == 'r'+'w' {
			if fd.rtimer != nil {
				fd.rtimer.Stop()
			}
			fd.rtimer = nil
		}
		if mode == 'w' || mode == 'r'+'w' {
			if fd.wtimer != nil {
				fd.wtimer.Stop()
			}
			fd.wtimer = nil
		}
	} else {
		// 计时器过期后中断I/O操作
		if mode == 'r' || mode == 'r'+'w' {
			fd.rtimer = time.AfterFunc(d, func() {
				fd.rmu.Lock()
				fd.rtimedout.setTrue()
				if fd.raio != nil {
					fd.raio.Cancel()
				}
				fd.rmu.Unlock()
			})
		}
		if mode == 'w' || mode == 'r'+'w' {
			fd.wtimer = time.AfterFunc(d, func() {
				fd.wmu.Lock()
				fd.wtimedout.setTrue()
				if fd.waio != nil {
					fd.waio.Cancel()
				}
				fd.wmu.Unlock()
			})
		}
	}
	if !t.IsZero() && d < 0 {
		// 中断当前I/O操作
		if mode == 'r' || mode == 'r'+'w' {
			fd.rtimedout.setTrue()
			if fd.raio != nil {
				fd.raio.Cancel()
			}
		}
		if mode == 'w' || mode == 'r'+'w' {
			fd.wtimedout.setTrue()
			if fd.waio != nil {
				fd.waio.Cancel()
			}
		}
	}
	return nil
}

// 仅在计划9上，公开对网络代码的锁定。

// ReadLock包装FD.ReadLock。
func (fd *FD) ReadLock() error {
	return fd.readLock()
}

// ReadUnlock包装FD.ReadUnlock。
func (fd *FD) ReadUnlock() {
	fd.readUnlock()
}

func isHangup(err error) bool {
	return err != nil && stringsHasSuffix(err.Error(), "Hangup")
}

func isInterrupted(err error) bool {
	return err != nil && stringsHasSuffix(err.Error(), "interrupted")
}

// IsPollDescriptor报告轮询器是否正在使用fd描述符。
// 仅用于测试。
func IsPollDescriptor(fd uintptr) bool {
	return false
}

// RawControl为非IO 
// 操作调用用户定义的函数f。
func (fd *FD) RawControl(f func(uintptr)) error {
	return errors.New("not implemented")
}

// RawRead调用用户定义的函数f进行读取操作。
func (fd *FD) RawRead(f func(uintptr) bool) error {
	return errors.New("not implemented")
}

// rawrite调用用户定义的函数f进行写入操作。
func (fd *FD) RawWrite(f func(uintptr) bool) error {
	return errors.New("not implemented")
}
